package gti310.tp4;

import java.util.*;

/**
 * La classe BlocBreaker parcours la matrice3D de couleurs reçu en paramètre 
 * dans le constructeur et contient la méthode diviserBlock qui segmente la
 * matrice en bloc 8x8. 
 * 
 * @author Fredy Alexander Bonilla
 * @date 2014-12-03
 *
 */
public class ImageBlockMaker {

	//La matrice3D de couleur qui sera traité
	private double [][][] matrixColor;
	private ArrayList<double[][]> blockList;
	private ArrayList<ArrayList<double[][]>> componentList;
	private boolean continuer=false;

	/**
	 * Constructeur de la classe BlockBreaker. Reçoit en paramètre une matrice3D
	 * de couleurs.  
	 * 
	 * @param matrixColor
	 */
	public ImageBlockMaker (double [][][] matrixColor){
		this.matrixColor = matrixColor;
	}

	/**
	 * Constructeur de la classe BlockBreaker. Reçoit en paramètre une liste 
	 * adjacente contenant des blocs 8x8 provenant de la DCT inverse. 
	 * 
	 * @param componentList
	 */
	public ImageBlockMaker (ArrayList<ArrayList<double[][]>> componentList){
		this.componentList = componentList;
	}

	/**
	 * Retourne la liste des composants
	 * @return blockList
	 */
	public ArrayList<ArrayList<double[][]>> getComponentList(){
		return componentList;
	}

	/**
	 * Retourne la matrice 3D des tables de couleurs
	 * @return matrixColor
	 */
	public double [][][] getMatrixColor(){
		return matrixColor;
	}

	/**
	 * La méthode diviserBlock valide les dimensions de la matrice3D avant de 
	 * procéder au découpage de bloc 8x8.
	 */
	public void diviserBlock (){

		double[][] block = null;
		double[][] testblock = new double[8][8];
		componentList = new ArrayList<ArrayList<double[][]>>();
		int posX = 0;
		int posY = 0;

		//Validation de des dimension de la matrice 3D

		continuer = validerDimension(matrixColor[0].length, matrixColor[0][0].length);

		if(continuer){
			//Parcour de la matrice 3D
			for(int k=0; k<matrixColor.length; k++){

				//Creation d'une nouvelle liste de bloc 8x8.
				blockList = new ArrayList<double[][]>();

				for(int i=0;i<matrixColor[k].length;i++){
					for(int j=0;j<matrixColor[k][i].length;j++){

						//Arrêt du parcour à chaque délimitation d'un bloc 8x8
						if((i+1)%8 == 0 && (j+1)%8 == 0){

							//Creation d'un nouveau block 8x8
							block = new double[8][8];

							posY = i;
							posX = j;

							//Remplissage du bloc 8x8
							for(int a=7; a>-1; a--){

								posY = j;
								for(int b=7; b>-1; b--){

									block[a][b] = matrixColor[k][posY][posX];
									posY--;
								}
								posX--;
							}

							//Ajout d'un bloc d'image dans le ArrayList
							blockList.add(block);

							//Reinitialisation du block de 8x8 temporaire
							block=null;
						}

					}//Fin du parcour de chaque colone
				}//Fin du parcours de chaque ligne

				//Ajout de la liste des bloc 8x8 a la liste des composants. 
				componentList.add(blockList);

				//Réinitialisation de la liste de bloc 8x8
				blockList = null;

			}//Fin du parcour des 3 dimensions

			/**
			 * Test d'impression pour afficher les valeurs
			 */

			testblock = componentList.get(0).get(0);
			for(int a=0; a<8; a++){
				for(int b=0; b<8; b++){
					System.out.print(Math.round(testblock[a][b])+" ");
				}
				System.out.println();
			}
		}//fin if
		else{
			System.out.println("La compression ne peut pas s'effectuer");
		}
	}

	/**
	 * La méthode reçoit les dimensions de hauteur et largeur d'une matrice.
	 * Elle retourne TRUE si les valeurs s'agit de multiple de 8 et FALSE si ce
	 * n'est pas le cas. 
	 * 
	 * @param heigh
	 * @param width
	 * @return validated
	 */
	public boolean validerDimension(int heigh, int width){

		boolean validated=false;

		if((heigh%8) == 0 && (width%8) == 0){
			validated = true;
		}
		else{
			System.out.println("Les dimension d'une des matrice n'Est pas "
					+ "divisible par bloc de 8x8 egaux");
			validated = false;
		}

		return validated;
	}

	/**
	 * 
	 */
	public void reunirBloc(){

		int matrixSize1 = componentList.get(0).size();
		int matrixSize2 = componentList.get(1).size();
		int matrixSize3 = componentList.get(2).size();
		double[][] blockTemp = null;
		matrixColor = new double [matrixSize1][matrixSize2][matrixSize3];
		int posX = 0;
		int posY = 0;
		int compteur = 0;

		//Parcour de la matrice 3D
		for(int k=0; k<matrixColor.length; k++){
			for(int i=0;i<matrixColor[k].length;i++){
				for(int j=0;j<matrixColor[k][i].length;j++){

					//Positionnement dans la matrice3D par multiple de 8
					if((i+1)%8 == 0 && (j+1)%8 == 0){

						posY = i;
						posX = j;

						blockTemp = new double[8][8];
						blockTemp = componentList.get(k).get(compteur);


						//Remplissage de la matrice par bloc
						for(int a=7; a>-1; a--){

							posY = j;
							for(int b=7; b>-1; b--){

								matrixColor[k][posY][posX] = blockTemp[a][b];
								posY--;
							}
							posX--;
						}
						
						//Passage au prochain bloc de 8x8
						compteur++;
						
						//Réinitialisation du block 8x8 temporaire
						blockTemp=null;
						
					}//Fin de la condition if
					
				}//fin du parcour de chaque colone
			}//fin du parcours de chaque ligne
		}//Fin du parcour des 3 dimensions
	}//Fin de la méthode

}
